#include <iostream>
#include "tcpclient.h"
#include "protocol.h"


TCPClient::TCPClient(QObject *parent)
{
    this->setParent(parent);
    this->_idCommand = 0;
    this->initCommands();
    this->_readingHeader = NULL;
    this->setReadMod(readingHeader, sizeof(CSProtocol::Header));
    connect(&this->_socket, SIGNAL(readyRead()), this, SLOT(readData()));
    connect(&this->_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
}


void TCPClient::readData()
{
    if (this->_socket.bytesAvailable() < this->_curReadSize)
        return;
    QByteArray data = this->_socket.read(this->_curReadSize);
    qDebug() << "Bytes available" << this->_socket.bytesAvailable();
    if (this->_curReadingMod == readingHeader)
    {
        delete this->_readingHeader;
        this->_readingHeader = new CSProtocol::Header();
        memcpy(this->_readingHeader, (CSProtocol::Header*) data.data(), sizeof(CSProtocol::Header));
        qDebug() << "Length Dataheader => " << this->_readingHeader->dataLength;
        if (this->_readingHeader->dataLength == 0)
            this->readToCmd(NULL);
        else
            this->setReadMod(readingData, this->_readingHeader->dataLength);
    }
    else
    {
        this->readToCmd((CSProtocol::IData*)data.data());
        this->setReadMod(readingHeader, sizeof(CSProtocol::Header));
    }
    if (this->_socket.bytesAvailable() > 0)
        this->readData();
}

void TCPClient::writeData(CSProtocol::Header &header, CSProtocol::IData *data)
{
    time_t t;
    time(&t);
    header.timestamp = t;
    header.id = this->_idCommand;
    this->_socket.write((char*)&header, sizeof(CSProtocol::Header));
    if (header.dataLength > 0)
        this->_socket.write((char*)data, header.dataLength);
    this->_waitForCmd[this->_idCommand] = data;
    this->incIdCommand();
}

void TCPClient::readToCmd(CSProtocol::IData *data)
{
    if (this->_waitForCmd.count(this->_readingHeader->id))
    {
        this->_waitForCmd[this->_readingHeader->id]->receiveTreat(*this, data);
        delete this->_waitForCmd[this->_readingHeader->id];
        this->_waitForCmd.erase(this->_readingHeader->id);
    }
    else if (this->_readingHeader->spontaneous
             && this->_commands.count(this->_readingHeader->code))
    {
        CSProtocol::IData *command = (this->*this->_commands[this->_readingHeader->code])();
        command->receiveTreat(*this, data);
        delete command;
    }
    else
        qDebug() << "Unknown command(" << this->_readingHeader->code << ") id(" << this->_readingHeader->id << ")";
}

void TCPClient::socketError(QAbstractSocket::SocketError socketError)
{
    qDebug() << socketError;
    this->_socket.abort();
    // TODO ANTOINE repop a la fenetre de demarrage et pop une error
}

void TCPClient::setReadMod(eReadingMod mod, int size)
{
    this->_curReadingMod = mod;
    this->_curReadSize = size;
}

void TCPClient::initCommands()
{
    this->_commands[CSProtocol::Welcome::code] = &TCPClient::createWelcome;
}
